STM32 串口DMA发送 您所在的位置:网站首页 Channel7 Invasion STM32 串口DMA发送

STM32 串口DMA发送

2023-02-19 05:39| 来源: 网络整理| 查看: 265

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出

GPIO_Init(GPIOA, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//USART2 RX引脚初始化

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//悬空输入

GPIO_Init(GPIOA, &GPIO_InitStructure);

}

接下去当然是串口的配置了,代码如下:

/*************************************************************

Function : USAETDMA_USART2_Init

Deion: 串口2初始化

Input : none

return : none

*************************************************************/

static void USAETDMA_USART2_Init(void)

{

USART_InitTypeDef USART_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);//USART2时钟初始化

USART_InitStructure.USART_BaudRate = 115200;//设置波特率

USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据位

USART_InitStructure.USART_StopBits = USART_StopBits_1;//1位停止位

USART_InitStructure.USART_Parity = USART_Parity_No;//没有校验位

USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//没有硬件流控制

USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//全双工模式

USART_Init(USART2, &USART_InitStructure);//初始化串口2

USART_DMACmd(USART2, USART_DMAReq_Tx, ENABLE);//打开DMA发送请求

USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//打开串口接收中断

USART_Cmd(USART2, ENABLE);//打开串口

}

上面说过,USART1已经被使用了,所以,选择USART2来做文章。这里设置USART2的波特率为115200,8位数据位,1位停止位,没有校验位,不使用硬件流控制,打开串口的全双工,并且打开串口的DMA发送功能与中断接收功能。这样的话,串口就配置好了!

在下去就要配置触DMA了,USART2的Tx对应着DMA1的CH7,下面就要配置下DMA1的CH7。代码如下:

#define USART2_DR_Base 0x40004404 //串口2的数据基地址

char *TxBuffer = "USART2:DMA Tx and Rx Interrupt\r\n";//发送缓冲

DMA_InitTypeDef DMA_InitStructure;

/*************************************************************

Function : USARTDMA_DMA_Init

Deion: DMA初始化,USART2 TX对应着DMA1的channel7

Input : none

return : none

*************************************************************/

static void USARTDMA_DMA_Init(void)

{

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

DMA_DeInit(DMA1_Channel7);//USART2对应着DMA1的CH7

DMA_InitStructure.DMA_PeripheralBaseAddr = USART2_DR_Base;//DMA的外设地址设置为USART2的数据寄存器基地址

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer;//DMA数据缓冲地址

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//内存作为数据的传输的数据源

DMA_InitStructure.DMA_BufferSize = strlen(TxBuffer);//要设置DMA缓冲大小

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址寄存器不变

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址寄存器不自增

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据宽度为8位

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//内存数据宽度为8位

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//工作在寻常模式

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;//DMA优先级非常高

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;//关闭DMA内存到内存的传输

DMA_Init(DMA1_Channel7, &DMA_InitStructure);//初始化DMA1的CH7

DMA_Cmd(DMA1_Channel7, ENABLE);//打开DMA1的CH7通道

}

DMA的外设地址当然要设置USART2的数据寄存器了,也就是上面的USART2_DR_Base,这个地址可以查看《STM32参考手册得到》,或者可以直接写USART2->DR就可以了。接下去设置DMA的数据缓冲地址,让它指向数据缓地址TxBuffer,并设置DMA的缓冲大小,因为TxBuffer是指针,所以要获得它所指向的数据的长度需要用strlen()函数,使用这个函数当然要先包含string.h头文件。DMA的配置还要设置其他的配置,如设置数据宽度为字节,内存数据宽度为字节等。最后再初始化DMA1的通道7,USART2正是对应着DMA1的通道7。

串口使用的DMA发送,而用中断接收。所以要配置下串口2的中断,设置中断优先级为1。代码如下:

/*************************************************************

Function : USARTDMA_Int_Init

Deion: 串口中断初始化

Input : none

return : none

*************************************************************/

static void USARTDMA_Int_Config(void)

{

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; //设置USART2的中断

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //优先级为1

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}

还要编写一个总函数:USARTDMA_Init()来初始化上面的代码,代码如下:

/*************************************************************

Function : USARTDMA_Init

Deion: 串口DMA发送初始化

Input : none

return : none

*************************************************************/

void USARTDMA_Init(void)

{

USARTDMA_GPIO_Init();

USAETDMA_USART2_Init();

USARTDMA_DMA_Init();

USARTDDMA_Int_Config();

}

串口DMA初始化完后,还要编写一个串口DMA的发送函数,代码如下:

/*************************************************************

Function : USARTDMA_SendStr

Deion: DMA发送字符串

Input : str-字符串的首地址 i-要发送的数据长度

return : none

*************************************************************/

void USARTDMA_SendStr(char *str, u16 i)

{

while (DMA_GetFlagStatus(DMA1_FLAG_TC7) == RESET);//等待DMA数据传输完毕

DMA_DeInit(DMA1_Channel7);/重置DMA1的CH7

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)str;//设置DMA缓冲区地址

DMA_InitStructure.DMA_BufferSize = i;//要传送数据长度

DMA_Init(DMA1_Channel7, &DMA_InitStructure);//初始化DMA1的CH7

DMA_Cmd(DMA1_Channel7, ENABLE);//打开DMA的通道7,这时候数据就发送出去了!

}

要想让DMA发送串口数据,首先要做的是检测DMA是否传输完毕,如果DMA忙着,就等待DMA空闲下来,重置DMA2的通道7,然后重新设置下DMA的数据缓冲与缓冲长度,最后在打开DMA的通道,这样的话DMA就自动将数据从串口发送出去了。

最后是DMATx.h的代码,在这个头文件中,要声明两个函数,这样的话,就可以在其他的文件调用了,代码如下:

#ifndef __USARTDMA_H__

#define __USARTDMA_H__

#include "stm32f10x.h"

#include "string.h"

void USARTDMA_Init(void);

void USARTDMA_SendStr(char *str, u16 i);

#endif

3、stm32f10x_it.c文件的修改

stm32f10x_it.c文件的中要添加USART2的中断服务程序,让串口接受什么数据就发送什么数据。代码如下:

/*************************************************************

Function : USART2_IRQHandler

Deion: 串口2中断服务程序

Input : none

return : none

*************************************************************/

void USART2_IRQHandler(void)

{

if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)

{

USART_SendData(USART2,USART_ReceiveData(USART2));//发送收到的字节

while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);//等待发送完成

}

}

4、main函数的编写

在main函数中,让不断地让串口DMA发送数据,代码如下:

extern char *TxBuffer;

/*************************************************************

Function : main

Deion: main入口

Input : none

return : none

*************************************************************/

int main(void)

{

BSP_Init();

USARTDMA_Init();

PRINTF("\nmain() is running!\r\n");

while(1)

{

1_Toggle();

TxBuffer = "Hello World!\r\n";

USARTDMA_SendStr(TxBuffer, strlen(TxBuffer));

Delay_ms(1000);

TxBuffer = "I glad to see you!\r\n";

USARTDMA_SendStr(TxBuffer, strlen(TxBuffer));

Delay_ms(1000);

}

}

想要让DMA发送数据,只要给让TxBuffer指向要发送数据的地址,然后再调用串口DMA发送函数USARTDMA_SendStr()就可以了发送数据了。

5、测试

用串口线将开发板与电脑连接,然后打开软件,就可以接收到开发板发送过来的数据,现象如下:

开发板会轮流发送“Hello World!”与“I grad to see you!”,然后后串口调试软件给开发板发送什么数据串口调试软件就会接收到什么数据。这里发送“Me too”,串口调试软件也就接收到了字符串“Me too”。

原文链接:返回搜狐,查看更多



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有